package uk.ac.strath.cis.metric_spaces.distance;

import java.util.Set;

import uk.ac.strath.cis.metric_spaces.framework.FingerPrintProcessor;
import uk.ac.strath.cis.metric_spaces.framework.ProcessableDistance;

import com.google.common.collect.Sets;

public class JaccardDistance<E> implements
        ProcessableDistance<E, FingerPrintProcessor<E, Set<?>>> {

    private FingerPrintProcessor<E, Set<?>> processor;

    /**
     * Sets the type of processor used in computing the distace
     */
    public void setProcessor(FingerPrintProcessor<E, Set<?>> processor) {
        this.processor = processor;
    }

    /**
     * Computes the distance between two items in the space
     */
    public double distance(E e1, E e2) {
        processor.process(e1);
        Set<?> fp1 = processor.getFingerPrint();
        processor.process(e2);
        Set<?> fp2 = processor.getFingerPrint();
        return distance(fp1, fp2);
    }

    private double distance(Set<?> fp1, Set<?> fp2) {
        double unionSize = Sets.union(fp1, fp2).size();
        double intersectionSize = Sets.intersection(fp1, fp2).size();
        return (unionSize - intersectionSize) / unionSize;
    }

}
